//ShadowMapData.h
//Created 21/01/14
//Created By Daniel Bowler
//
//Contains all the data required to support shadow mapping in this engine. Initially
//will be a single directional light source. .

#pragma once

//We need to create D3D resources
#include "d3dUtil.h"

//For XNA::Frustum
#include "xnacollision.h"

class VirtualCamera;

//Used to estimate the bounds of our demo scenes. We can use this as
//we are creating the scene manually. If not, then we would have to loop
//through the entire scene (in world space) and construct this
//bounding sphere. We can, of course, make it smaller than the scene
//so that less objects are drawn in the shadow map. 
struct ShadowMapBoundingSphere
{
	ShadowMapBoundingSphere() : Center(0.0f, 0.0f, 0.0f), Radius(0.0f) {}

	XMFLOAT3 Center;
	float Radius;
	float w;
	float d;

	void SetRadius(float width, float depth)
	{
		//Eg, say if we had a grid which is the widest object in the scene (width of 20 
		//and depth of 30) and we want every object on it to be rendered to the depth map,
		//then we would set Center to 0,0,0 and set Radius to sqrt(w/2 * w/2 + d/2*d/2)
		Radius = sqrt( ((width/2.0f) * (width/2.0f)) + ((depth/2.0f) * (depth/2.0f)) );
		w = width;
		d = depth;
	}
};

class DirecLightShadowMapData
{
public:
	//Constructor will create the depth map at the specified resolution - size is fixed
	//untill you destroy and recreate it. 
	DirecLightShadowMapData(ID3D11Device* device, 
		unsigned depthMapHeight, unsigned depthMapWidth,  //Depth map resolution
		DirectionalLight* directionalLightSource,		  //view/proj matricies. 
		ShadowMapBoundingSphere* sceneVolume);            //Used to build a boudning sphere around the scene.

	//Simply clears up D3D resources created by this class. 
	~DirecLightShadowMapData();

	//Pass a directional light whenever it changes - this will rebuild the view
	//and projection matricies. This will be used whenever the directional light
	//moves so we can simulate a day/night system.
	//
	//In our engine, called when we update the scene directional light. 
	void Update(DirectionalLight* updatedDirectionalLightSource, 
		ShadowMapBoundingSphere* updatedSceneVolume);

	//Manually updates the shadow map stuff. 
	void ManualUpdate(DirectionalLight* updatedDirectionalLightSource, 
		float translation,
		VirtualCamera* camera);

public:
	//Returns the light sources view matrix.
	XMMATRIX GetLightView();
	//Returns the light soruces projection matrix
	XMMATRIX GetLightProj();
	//Returns the NDC to tex space matrix. 
	XMMATRIX GetNDCToTex();

	//Returns the shadow map SRV to be fed in to shaders. 
	ID3D11ShaderResourceView* GetShadowMapSRV(){return srv;};
	//Returns the shadow map DSV which we render in to from the perspecitive
	//of the camera
	ID3D11DepthStencilView* GetShadowMapDSV(){return dsv;};
	//Returns the viewport
	D3D11_VIEWPORT* ReturnViewport(){return &viewport;};

private:
	//Resolution of the depth map
	unsigned shadowMapWidth;
	unsigned shadowMapHeight;

	//Light data - position vector and position
	XMFLOAT3 lightPos;
	XMFLOAT3 lightLook;

	//Light matricies
	XMFLOAT4X4 viewMatrix;
	XMFLOAT4X4 projMatrix;
	XMFLOAT4X4 toTexSpaceMatrix;

	//Viewport to render in to the shadow/depth map. 
	D3D11_VIEWPORT viewport;
	//Depth Stencil View - When rendering the depths from the viewpoint
	//of the light source, we write to a depth buffer. 
	ID3D11DepthStencilView* dsv;
	//Shader Resource View - Used as input when lighting. 
	ID3D11ShaderResourceView* srv;

private:
	//Private function that creates the depth map and views - Also inits the viewport
	//used when drawing to the shadow map. 
	void CreateShadowMapD3D(ID3D11Device* device);
};